﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using MQTTnet.Protocol;
using System.Reflection.Emit;
using System.Text;

namespace Mqtt {
    public class MqttPublisher {
        public  IMqttClient mqttClient;

        public async Task ConnectAsync() {
            var factory = new MqttFactory();
            mqttClient = factory.CreateMqttClient();

            var options = new MqttClientOptionsBuilder()
                .WithTcpServer("192.168.7.81", 1883)
                .WithClientId("Client1")
                .Build();

            mqttClient.UseDisconnectedHandler(async e => {
                Console.WriteLine("### DISCONNECTED FROM SERVER ###");
                await Task.Delay(TimeSpan.FromSeconds(5));

                try {
                    await mqttClient.ConnectAsync(options, CancellationToken.None);
                }
                catch {
                    Console.WriteLine("### RECONNECTING FAILED ###");
                }
            });

            mqttClient.UseApplicationMessageReceivedHandler(e => {
                Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
                Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
                Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
                Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
                Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
                Console.WriteLine();
            });

            try {
                await mqttClient.ConnectAsync(options, CancellationToken.None);
                Console.WriteLine("Connected to broker!");
            }
            catch (Exception ex) {
                Console.WriteLine($"Error: {ex}");
            }
        }
        public async Task DisconnectAsync() {
            if (mqttClient != null && mqttClient.IsConnected) {
                await mqttClient.DisconnectAsync();
                Console.WriteLine("Disconnected from broker.");
            }
            else {
                Console.WriteLine("Client is not connected.");
            }
        }

        public async Task PublishMessageAsync(string topic, string payload) {
            if (mqttClient == null || !mqttClient.IsConnected) {
                Console.WriteLine("Not connected to broker. Unable to publish message.");
                return;
            }

            var message = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(payload)
                .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
                .WithRetainFlag(false) // 是否保留消息
                .Build();

            await mqttClient.PublishAsync(message, CancellationToken.None);

            Console.WriteLine("Message published!");
        }
    }
}